﻿Public MustInherit Class element

    Public Contents As New List(Of Element)
    Public Parent As Element
    Public MustOverride Sub Draw(ByVal g As Graphics, ByVal P As Point)
    'Public MustOverride ReadOnly Property Size As Size
    Public MustOverride ReadOnly Property Width As Integer
    Public MustOverride ReadOnly Property Height As Integer

    Public ReadOnly Property Font As Font
        Get
            If Parent Is Nothing Then Return New Font("segoe ui", 9)
            Return Parent.Font
        End Get
    End Property

    Function Parse(ByVal Text As String) As String
        Do Until Text = ""
            If Text.StartsWith("</") Then
                Dim Pos = InStr(2, Text, "<")
                If Pos = 0 Then Return ""
                Return Mid(Text, Pos)
            ElseIf Text.StartsWith("<table") Then
                AddElement(New table, Text)
            ElseIf Text.StartsWith("<tr") Then
                AddElement(New tr, Text)
            ElseIf Text.StartsWith("<td") Then
                AddElement(New td, Text)
            ElseIf Text.StartsWith("<") Then
            Else
                Dim Pos = InStr(Text, "<")
                Dim Label As New label
                Label.Parent = Me
                Label.Inner = Mid(Text, 1, Pos - 1)
                Contents.Add(Label)
                Text = Mid(Text, Pos)
            End If
        Loop
        Return ""
    End Function

    Overridable Sub AddElement(ByVal e As element, ByRef Text As String)
        e.Parent = Me
        Contents.Add(e)
        Dim Pos = InStr(Text, ">")
        Dim Spos = InStr(Text, " ")
        If Spos > 0 And Spos < Pos Then
            Dim attr = Mid(Text, Spos + 1, Pos - Spos - 1)
            Dim a As New Dictionary(Of String, String)
            ParseAttributes(a, attr)
            e.SetAttributes(a)
        End If
        Text = e.Parse(Mid(Text, Pos + 1))
    End Sub

    Dim Inner As String
    Property Inside As String
        Get
            Return Inner
        End Get
        Set(ByVal Value As String)
            Inner = Value
            Contents.Clear()
            Parse(Value)
        End Set
    End Property

    Private Sub ParseAttributes(ByVal a As Dictionary(Of String, String), ByVal attr As String)
        Do
            attr = attr.Trim
            If attr = "" Then Exit Do
            Dim pos1 = InStr(attr, " ")
            Dim pos2 = InStr(attr, "=")
            If pos2 = 0 Then
                a.Add(attr, "")
            ElseIf pos1 > 0 AndAlso pos2 > pos1 AndAlso Mid(attr, pos1, pos2 - pos1).Trim <> "" Then
                a.Add(Mid(attr, 1, pos1 - 1), "")
                attr = Mid(attr, pos1 + 1)
            Else
                Dim attrname = Mid(attr, 1, pos2 - 1)
                attr = Mid(attr, pos2 + 1).Trim
                Dim c = If(Mid(attr, 1, 1) = """", """", " ")
                pos1 = InStr(2, attr & c, c)
                a.Add(attrname, Mid(attr, 1, pos1 - 1))
                attr = Mid(attr, pos1 + 1).Trim
            End If
        Loop
    End Sub

    Overridable Sub SetAttributes(ByVal a As Dictionary(Of String, String))
        For Each Item In a
            Select Case Item.Key
                Case "bgcolor" : Style.bgcolor = Item.Value
                Case "width" : Style.width = Item.Value
                Case "height" : Style.height = Item.Value
                Case "align" : Style.align = Item.Value
            End Select
        Next
    End Sub

    Property Style As New Style

    ReadOnly Property finalbgcolor As String
        Get
            If Style.bgcolor <> "" Then Return Style.bgcolor
            If Parent Is Nothing Then Return ""
            Return Parent.finalbgcolor
        End Get
    End Property

    Overridable ReadOnly Property MinWidth As Integer
        Get
            Return (From c In Contents Let a = c.MinWidth Select a).Sum
        End Get
    End Property
    Overridable ReadOnly Property MaxWidth As Integer
        Get
            Return (From c In Contents Let a = c.MaxWidth Select a).Sum
        End Get
    End Property
    Overridable Sub ResizeWidth(ByVal w As Integer)
        For Each Item In Contents
            Item.ResizeWidth(w)
        Next
    End Sub
    Overridable Sub ResizeHeight(ByVal h As Integer)
        For Each Item In Contents
            Item.ResizeHeight(h)
        Next
    End Sub

    Function MeasureText(ByVal Text As String, ByVal Font As Drawing.Font, ByVal Size As Drawing.Size) As Object
        Return TextRenderer.MeasureText(Text, Font, Size, TextFormatFlags.WordBreak)
    End Function

    Sub DrawText(ByVal g As Graphics, ByVal Text As String, ByVal Font As Drawing.Font, ByVal R As Rectangle, ByVal Color As Color, Align As String)
        Dim f As TextFormatFlags = TextFormatFlags.WordBreak
        If Align = "right" Then f = f Or TextFormatFlags.Right
        If Align = "center" Then f = f Or TextFormatFlags.HorizontalCenter
        TextRenderer.DrawText(g, Text, Font, R, Color, Drawing.Color.Transparent, f)
    End Sub

End Class

Public Class Style

    Public bgcolor As String = ""
    Public width As String = ""
    Public height As String = ""
    Public align As String = ""

    ReadOnly Property relativewidth As Boolean
        Get
            Return width.Contains("%")
        End Get
    End Property

    ReadOnly Property fixedwidth As Boolean
        Get
            Return width > "" And Not relativewidth
        End Get
    End Property

End Class